#!/usr/bin/env python
# A string abaixo nos mostra a utilidade deste script
"""
Script principal para rodar o daemon do servidor
"""

# Os import's vem apos a string de documentacao
import threading
import SocketServer
import getopt
import sys
from model import *
from utils import *
import socket

#constantes
HOST = "localhost"
PORT = 1939  #Porta padrao
USAGE_MESSAGE = """NeWar Server

Uso: %s [opcoes]

Lista de parametros:

    --help    
     -h        Mostra essa mensagem

    -p PORTA   Seleciona PORTA como a porta que o servidor escuta


""" % (sys.argv[0])
TIMEOUT = 60.


class ServerHandler(SocketServer.BaseRequestHandler):
	def setup(self):
		print "Conexao aberta com", self.client_address
		self.current_player = None

	def getline(self):
		line = ''
		while not self.server.close_threads.isSet():
			try:
				c = self.request.recv(1)
				if c == '\n':
					break
				else:
					line += c
			except:
				break
		return line

	def get_command(self):
		msg = self.getline()
		msg = msg.split(None, 1)
		while(len(msg) < 2):
			msg.append('')
		msg[0] = msg[0].lower()
		return msg

	def kill_server(self):
		self.server.close_threads.set()
		self.server.shutdown()

	def handle(self):
		while not self.server.close_threads.isSet():
			if not self.login_mode():
				break
			try:
				self.login_mode()
			except Exception, e:
				print "Exception found on thread. Quitting\n"
				print "Exception:", str(e)
				print 
				break

	def login_mode(self):
		while not self.server.close_threads.isSet():
			cmd, val = self.get_command()
			print self.client_address, " : ", cmd, val
			if cmd == "cadastro":
				nome, cor = val.split(None, 1)
		
				rlock = self.server.estado_do_jogo_rlock
				game  = self.server.game
				new_player = Player(game.evManager, nome, cor, self.client_address)
				try:
					with rlock:
						game.AddPlayer(new_player)
					self.current_player = new_player
					self.request.sendall("cadastroOk\n")
					self.is_ready_mode()
					self.request.sendall("fim\n")
					break
				except Exception, e:
					print "Falha no cadastro de ", val
					self.request.sendall("falhaCadastro " + str(e) + "\n")
			else:
				self.request.sendall("falhaComando Comando invalido\n")
	def is_game_ready(self):
		rlock = self.server.estado_do_jogo_rlock
		with rlock:
			return self.server.game.isEverybodyReady()
				
	def is_ready_mode(self):
		rlock = self.server.estado_do_jogo_rlock
		cmd, val = self.get_command()
		if cmd == "ready":
			with rlock:
				self.current_player.set_ready(True)
				if self.is_game_ready():
					self.server.shutdown()
					self.server.everybody_is_ready.set()
			self.server.everybody_is_ready.wait(TIMEOUT)
			if self.server.everybody_is_ready.isSet():
				with rlock:
					if not self.server.game_setup.isSet():
						self.server.game.distribuirTerritorios()
						self.server.game_setup.set()
					mes = "serverReady "
					players = self.server.game.GetPlayers()
					mes += str(len(players)) + " "
					for p in players:
						territories = self.server.game.territories_by_player[p.GetName()]
						mes += p.GetName() + ":" + p.GetColor() + " "
						mes += str(len(territories)) + " "
						for t in territories:
							mes += str(t[0]) + ":" + str(t[1]) + ":"
							mes += str(self.server.game.num_exercitos_territorio[tuple(t)]) + " "
					mes += "\n"
				print "Sending", mes
				self.request.sendall(mes)
			else:
				self.request.sendall("erro Timeout\n")
				self.kill_server()

	def finish(self):
		print "Conexao com", self.client_address, "fechada."
		if self.current_player:
			pass #fazer algo com um jogador que sai

class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
	_estado = "<undefined>"
	estado_do_jogo_rlock = threading.RLock()
	game = Game(EventManager(), decisor=True)
	close_threads = threading.Event()
	everybody_is_ready = threading.Event()
	game_setup = threading.Event()

def usage():
	"Mostra a utilizacao usual do servidor"
	print USAGE_MESSAGE
	
if __name__ == "__main__":
	try:
		opts, args = getopt.getopt(sys.argv[1:], "hp:", ["help"])
	except getopt.GetoptError, err:
		print str(err)
		usage()
		sys.exit(2)

	for o, a in opts:
		if o in ('-h', '--help'):
			usage()
			sys.exit()
		elif o == '-p':
			try:
				PORT = int(a)
			except:
				print "Porta invalida"
				sys.exit(2)
	server = ThreadedTCPServer((HOST, PORT), ServerHandler)
	print "O servidor esta rodando...\n"
	server.serve_forever()
